package com.google.gac.masai.getit;

import java.io.File;
import java.net.URI;
import java.net.URLConnection;
import java.util.Calendar;
import java.util.Date;

import org.apache.http.conn.ManagedClientConnection;

import android.app.Service;
import android.content.ContentValues;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.FileObserver;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;

public class DownloadWatcher extends Service {

	private String tag = "DownloadWatcher";
	private DownloadObserver mObs;
	private SharedPreferences mPreferences;

	private static final String[] PROJECTION = new String[] {
			DownloadLog.Logs._ID, // 0
			DownloadLog.Logs.COLUMN_NAME_TITLE, // 1
			DownloadLog.Logs.COLUMN_NAME_URI, // 2
			DownloadLog.Logs.COLUMN_NAME_TAG, // 3
			DownloadLog.Logs.COLUMN_NAME_CREATE_DATE // 4
	};

	// Global mutable variables
	private Uri mUri;
	private Cursor mCursor;

	public void onCreate() {
		mObs = new DownloadObserver("/sdcard/Download",
				FileObserver.CLOSE_WRITE, this);
		mObs.startWatching();
		mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
	}

	private class DownloadObserver extends FileObserver {
		private DownloadWatcher mDW;

		public DownloadObserver(String path, int mask, DownloadWatcher dw) {
			super(path, mask);
			mDW = dw;
		}

		public void onEvent(int event, String path) {
			Log.v("ONEVENT", "CHECK");
			mDW.fileDownloaded(path);
		}
	}

	public void fileDownloaded(String path) {
		File internalLoc = Environment.getDataDirectory();
		File externalLoc = Environment.getExternalStorageDirectory();
		String log = null;
		Log.w("DownloadWatcher", "getFilesDir: "
				+ getFilesDir().getAbsolutePath());
		Log.w("DownloadWatcher", "getFilesDir.exists: "
				+ getFilesDir().exists());
		boolean mounted = Environment.getExternalStorageState().equals(
				"mounted");

		String loc_perf = mPreferences.getString("location_pref", "NOVALUE");
		Log.e("DownloadWatcher", "location_pref: " + loc_perf);
		String cat_perf = mPreferences.getString("category_pref", "NOVALUE");
		Log.e("DownloadWatcher", "category_pref: " + cat_perf);
		boolean local_perf = mPreferences.getBoolean("localcopy_pref", false);
		Log.e("DownloadWatcher", "location_pref: " + local_perf);
		
		String spec_rule1 = mPreferences.getString("rule_one", "NOVALUE");
		String spec_rule2 = mPreferences.getString("rule_two", "NOVALUE");
		String spec_rule3 = mPreferences.getString("rule_three", "NOVALUE");
		
		String spec_folder1 = mPreferences.getString("folder_one", "NOVALUE");
		String spec_folder2 = mPreferences.getString("folder_two", "NOVALUE");
		String spec_folder3 = mPreferences.getString("folder_three", "NOVALUE");
		
		boolean rule1_on = mPreferences.getBoolean("first_special", false);
		boolean rule2_on = mPreferences.getBoolean("second_special", false);
		boolean rule3_on = mPreferences.getBoolean("third_special", false);
		

		Log.e("DownloadWatcher", "Externation Storage Dir is : " + externalLoc.getAbsolutePath());
		
		/*
		 * Upload Location
		 */
		String newPath = "";
		/*
		if (loc_perf.equals("DropBox")) {
			newPath += "/GetIt/";
		}
		else{
			newPath += externalLoc.getAbsolutePath() + "/GetIt/";
			Log.v("sd card", "ENABLED");
		} */
		
		newPath += externalLoc.getAbsolutePath() + "/GetIt/";
		Log.v("sd card", "ENABLED");

		/*
		 * Category
		 */
		File temp = new File(newPath);
		
		int place = path.lastIndexOf(".");
		String tempDir = path.substring(0, place);
		int place2 = tempDir.lastIndexOf("/");
		String myFile = tempDir.substring(place2 + 1);
		
		if (!(temp.exists() && temp.isDirectory()))
			temp.mkdir();
		// File Extensions
		if (rule1_on == true && myFile.toLowerCase().contains(spec_rule1.toLowerCase())) {
			newPath += (spec_folder1 + "/");
			log = spec_folder1;
		}
		else if (rule2_on == true && myFile.toLowerCase().contains(spec_rule2.toLowerCase())) {
			newPath += (spec_folder2 + "/");
			log = spec_folder2;
		}
		else if (rule3_on == true && myFile.toLowerCase().contains(spec_rule3.toLowerCase())) {
			newPath += (spec_folder3 + "/");
			log = spec_folder3;
		}
		else if (cat_perf.equals("Media Type (default)")) {
			String mimeType = URLConnection.guessContentTypeFromName(path);

			if (mimeType == null) {
				int extensionStart = path.lastIndexOf(".");
				if (extensionStart != -1){
					log = path.substring(extensionStart + 1);
					newPath += log + "/";
				}
				else{
					log = "misc";
					newPath += "misc/";
				}
					
			} else {
				Log.v(tag, "mimeType = " + mimeType);
				int index = mimeType.indexOf("/");
				log = mimeType.substring(0, index + 1);
				newPath += log;
				
			}
		}
		// File Name
		else if (cat_perf.equals("File Name")) {
			/* Need to handle this elsewhere
			Log.v(tag, "File Names selected");
			// Let the user input the rule for file names.
			// Get the name arrays from the preference settings
			String[] nameRules;
			nameRules = null;
			int index = 0;
			Boolean isContain = false;
			for (int i = 0; i < nameRules.length; i++) {
				if (path.contains(nameRules[i])) {
					isContain = true;
					index = i;
					log = nameRules[i];
					break;
				}
			}
			if (isContain) {
				newPath += nameRules[index];
			} else {
				newPath += "misc";
				log = "misc";
			}
			*/
			
			String filename = mPreferences.getString("Filename Choice", "NOVALUE");
			Log.v(tag, "nameRule = " + filename);
			if (filename.equals("firstletter")) {
				int placeholder = path.lastIndexOf(".");
				String tempDirec = path.substring(0, placeholder);
				int placeholder2 = tempDirec.lastIndexOf("/");
				String firstLetter = tempDirec.substring(placeholder2 + 1, placeholder2 + 2);
				log = firstLetter;
				newPath += ("First letter of file name: " + firstLetter + "/");
			}
			else if (filename.equals("namelength")) {
				
				newPath += ("File name length: " + myFile.length() + "/");
				log = ""+myFile.length();
			}
			
		}else{
			int extensionStart = path.lastIndexOf(".");
			if (extensionStart != -1) {
				log = path.substring(extensionStart + 1);
				newPath += log + "/";
			} else {
				log = "misc";
				newPath += "misc/";
			}
		}

		Log.w("DownloadWatcher", "file downloaded: " + path);
		Log.w("DownloadWatcher", "moving to: " + newPath);

		File newDir = new File(newPath);
		if (!(newDir.exists() && newDir.isDirectory()))
			newDir.mkdir();
		File f = new File("/mnt/sdcard/Download/" + path);
		File f2 = new File(newPath + path);
		Log.v(tag, "old file exists: " + f.exists());
		Log.v(tag, "new file exists: " + f2.exists());
		if (!f.exists())
			return;
		mUri = getContentResolver().insert(
				Uri.parse("content://com.google.provider.DownloadLog/logs"),
				null);
		Log.v("mUri", mUri.toString());
		ContentValues values = new ContentValues();
		values.put(DownloadLog.Logs.COLUMN_NAME_TITLE, f2.getName());
		values.put(DownloadLog.Logs.COLUMN_NAME_URI, f2.getAbsolutePath());
		values.put(DownloadLog.Logs.COLUMN_NAME_TAG, log);
		Calendar date = Calendar.getInstance();

		String now = (date.get(Calendar.YEAR) + "/" + (date.get(Calendar.MONTH)+1) + "/" + date.get(Calendar.DAY_OF_MONTH)
				+ " " + date.get(Calendar.HOUR_OF_DAY) + ":" + date.get(Calendar.MINUTE));
		values.put(DownloadLog.Logs.COLUMN_NAME_CREATE_DATE,
				now);
		getContentResolver().update(mUri, values, null, null);
		//
		SharedPreferences.Editor edit = mPreferences.edit();
		// // SharedPreferences mPreferences;
		// // mPreferences =
		// PreferenceManager.getDefaultSharedPreferences(this);
		
		edit.putString("LATEST_PATH", newPath); // was newPath before.
		
		// int numDownloads = mPreferences.getInt("numDownloads", 0);
		// Calendar rightNow = Calendar.getInstance();
		// int myMonth = rightNow.get(Calendar.MONTH);
		// int myDay = rightNow.get(Calendar.DAY_OF_MONTH);
		// int myYear = rightNow.get(Calendar.YEAR);
		// int myHour = rightNow.get(Calendar.HOUR_OF_DAY);
		// int myMinute = rightNow.get(Calendar.MINUTE);
		// int mySecond = rightNow.get(Calendar.SECOND);
		// edit.putString("download" + numDownloads, "Downloaded " + f.getName()
		// + " on " + myMonth + "/" + myDay + "/" + myYear + " at "
		// + myHour + ":" + myMinute + ":" + mySecond + ".");
		// edit.putInt("numDownloads", numDownloads + 1);
		edit.commit();

		if (loc_perf.equals("DropBox")) {
			
			/*Update the LATEST_PATH to the correct value in Shared Prefs
			 * When dropbox is connected the newPath string is missing the /mnt/sdcard prefix. 
			 */
			String latest_path = Environment.getExternalStorageDirectory().getAbsolutePath() + newPath; 
			edit.putString("LATEST_PATH", latest_path); // save the correct path info overwriting prior incorrect value. 
			edit.commit(); // save the changes 
			
			SharedPreferences data = this.getSharedPreferences(DropBox.CRED,
					MODE_PRIVATE);

			String key = data.getString("ACCESS_KEY", null);
			String secret = data.getString("ACCESS_SECRET", null);

			if (key == null || secret == null) { // then user has not connected
													// a dropbox account. SO do
													// nothing
				Log.d("DROPBOX",
						"User has not connected dropox account so we can't upload file to dropbox yet");
				return;
			}

			// otherwise use retrieved token to connect to dropbox.
			String[] keys = { key, secret };

			Log.d("DROPBOX", "Download Watcher Retrieved tokens : key=" + key
					+ " ; secret=" + secret);

			DropBox d = null;
			try {
				d = new DropBox(keys);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			if (!d.isConnected()) {
				Log.d("DROPBOX",
						"Connecting to dropbox failed using tokens failed Upload Halted. key="
								+ key + " ; secret=" + secret);
				return; // stop here
			}

			UploadAsync uplo = new UploadAsync(this, f.getAbsolutePath(),
					newPath, !local_perf);
			uplo.execute(d);
		} else if (f.renameTo(f2))
			Log.w("DownloadWatcher", "Move successful");
		else
			Log.w("DownloadWatcher", "Move not successful");
	}

	public class LocalBinder extends Binder {
		DownloadWatcher getService() {
			return DownloadWatcher.this;
		}
	}

	private final IBinder mBinder = new LocalBinder();

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

}
